package cn.tedu.baking.controller;

import cn.tedu.baking.mapper.UserMapper;
import cn.tedu.baking.pojo.dto.UserLoginDTO;
import cn.tedu.baking.pojo.dto.UserRegDTO;
import cn.tedu.baking.pojo.dto.UserUpdateDTO;
import cn.tedu.baking.pojo.entity.User;
import cn.tedu.baking.pojo.vo.UserVO;
import cn.tedu.baking.response.JsonResult;
import cn.tedu.baking.response.StatusCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.util.Date;

@Api(tags = "用户接口")
@RestController
@RequestMapping("/v1/users/")
@Slf4j
public class UserController {
    @Value("${filePath}")
    private String dirPath;

    @Autowired
    UserMapper mapper;

    // 密码加密器
    @Autowired
    PasswordEncoder encoder;

    // 认证管理器
    @Autowired
    AuthenticationManager manager;

    /**
     * 注册接口
     * @param userRegDTO:用户实体
     * @return: JsonResult
     */
    @PostMapping("reg")
    @ApiOperation(value = "注册接口")
    public JsonResult reg(@RequestBody UserRegDTO userRegDTO) {
        try {
            log.info("userRegDTO:{}", userRegDTO);
            // 判断用户名是否已存在
            UserVO userVO = mapper.selectByUserName(userRegDTO.getUserName());
            if (userVO != null) {
                return new JsonResult(StatusCode.USERNAME_ALREADY_EXISTS);
            }
            User user = new User();
            BeanUtils.copyProperties(userRegDTO, user);
            user.setCreateTime(new Date());
            //密码加密，否则会直接将明文密码存入数据库
            user.setPassword(encoder.encode(user.getPassword()));
            //设置默认头像
            user.setImgUrl("/imgs/Avatar.png");
            //插入数据
            mapper.insert(user);
            log.info("user:{}", user);
            return JsonResult.ok();
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    /**
     * 登录接口
     *
     * @param userLoginDTO:用户实体
     * @return
     */
    @PostMapping("login")
    public JsonResult login(@RequestBody UserLoginDTO userLoginDTO) {
        try {
            log.info("userLoginDTO:{}", userLoginDTO);
            //创建认证令牌
            UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(userLoginDTO.getUserName(), userLoginDTO.getPassword());
            //开启认证流程
            Authentication result = manager.authenticate(upat);
            //将认证结果保存到Security上下文
            SecurityContextHolder.getContext().setAuthentication(result);
            //将认证成功的用户信息响应给客户端
            return JsonResult.ok(result.getPrincipal());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    @GetMapping("logout")
    public JsonResult logout() {
        try {
            SecurityContextHolder.clearContext();
            return JsonResult.ok();
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    /**
     * 更新用户信息
     * @param userUpdateDTO
     * @return
     */
    @PostMapping("update")
    public JsonResult update(@RequestBody UserUpdateDTO userUpdateDTO) {
        try {
            //判断出是否需要更换图像
            if (userUpdateDTO.getImgUrl() != null) {
                String imgUrl = mapper.selectImgUrlById(userUpdateDTO.getId());
                //删除旧图像
                new File(dirPath + imgUrl).delete();
            }
            User user = new User();
            BeanUtils.copyProperties(userUpdateDTO, user);
            mapper.update(user);
            log.info("user:{}", user);
            return JsonResult.ok();
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('ADMIN')")
    @GetMapping("")
    public JsonResult list() {
        try {
            return JsonResult.ok(mapper.select());
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('ADMIN')")
    @PostMapping("{id}/delete")
    public JsonResult delete(@PathVariable Long id) {
        try {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            Object principal = auth.getPrincipal();
            User user = new User();
            BeanUtils.copyProperties(principal, user);
            log.info("user:{}", user);
            if (user.getId() == id || user.getId().equals(id)) {
                return JsonResult.fail("无法删除当前账户");
            }
            mapper.deleteById(id);
            return JsonResult.ok();
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('ADMIN')")
    @PostMapping("{id}/{isAdmin}/change")
    public JsonResult change(@PathVariable Long id,
                             @PathVariable Integer isAdmin) {
        try {
            User user = new User();
            user.setId(id);
            user.setIsAdmin(isAdmin);
            mapper.update(user);
            return JsonResult.ok();
        } catch (Exception e) {
            return JsonResult.fail(e.getMessage());
        }
    }
}
